// Common.hpp
#ifndef YOLOS_EDGEPLATFORM_COMMON_HPP
#define YOLOS_EDGEPLATFORM_COMMON_HPP

/**
 * @file Common.hpp
 * @brief YOLOs-CPP-EdgePlatform 通用数据结构和工具
 *
 * @author FANKYT
 * @date 2025
 */

#include <vector>
#include <string>
#include <opencv2/opencv.hpp>

namespace yolos_edgeplatform {

/**
 * @brief 表示图像中边界框的结构体
 */
struct BoundingBox {
    float x;      /**< 左上角 X 坐标 */
    float y;      /**< 左上角 Y 坐标 */
    float width;  /**< 边界框宽度 */
    float height; /**< 边界框高度 */

    BoundingBox() : x(0), y(0), width(0), height(0) {}

    BoundingBox(float x_, float y_, float width_, float height_)
        : x(x_), y(y_), width(width_), height(height_) {}

    /**
     * @brief 计算边界框的面积
     */
    float area() const { return width * height; }
};

/**
 * @brief 表示单个检测结果的结构体
 */
struct Detection {
    BoundingBox box; /**< 检测对象的边界框 */
    float conf;      /**< 检测的置信度分数 */
    int classId;     /**< 检测对象的类别ID */

    Detection() : conf(0.0f), classId(-1) {}

    Detection(const BoundingBox &box_, float conf_, int classId_)
        : box(box_), conf(conf_), classId(classId_) {}
};

/**
 * @brief 预处理方法枚举
 */
enum class PreprocessType {
    RESIZE = 0,    /**< 直接缩放 */
    LETTERBOX = 1  /**< 保持宽高比缩放（填充灰边） */
};

/**
 * @brief 模型输入格式类型
 */
enum class InputImageType {
    RGB = 0,    /**< RGB 格式 (NCHW, uint8-128 量化) */
    NV12 = 1    /**< NV12 格式 (YUV420SP) */
};

/**
 * @brief 表示姿态估计中关键点的结构体
 */
struct KeyPoint {
    float x;          /**< 关键点 X 坐标 */
    float y;          /**< 关键点 Y 坐标 */
    float confidence; /**< 关键点置信度 */

    KeyPoint() : x(0), y(0), confidence(0) {}

    KeyPoint(float x_, float y_, float conf_ = 0)
        : x(x_), y(y_), confidence(conf_) {}
};

/**
 * @brief 表示姿态检测结果的结构体
 */
struct PoseDetection {
    BoundingBox box;              /**< 人体边界框 */
    float conf;                   /**< 检测置信度 */
    int classId;                  /**< 类别ID (通常是 person) */
    std::vector<KeyPoint> keypoints; /**< 关键点列表 (COCO: 17个关键点) */

    PoseDetection() : conf(0.0f), classId(-1) {}

    PoseDetection(const BoundingBox &box_, float conf_, int classId_)
        : box(box_), conf(conf_), classId(classId_) {}
};

/**
 * @brief 表示实例分割结果的结构体
 */
struct Segmentation {
    BoundingBox box;  /**< 对象边界框 */
    float conf;       /**< 检测置信度 */
    int classId;      /**< 类别ID */
    cv::Mat mask;     /**< 分割掩码 (单通道,与原图同尺寸) */

    Segmentation() : conf(0.0f), classId(-1) {}

    Segmentation(const BoundingBox &box_, float conf_, int classId_)
        : box(box_), conf(conf_), classId(classId_) {}
};

/**
 * @brief COCO 人体姿态关键点骨架连接
 *
 * 17个关键点索引:
 * 0: 鼻子, 1-2: 眼睛, 3-4: 耳朵, 5-6: 肩膀
 * 7-8: 肘部, 9-10: 手腕, 11-12: 髋部, 13-14: 膝盖, 15-16: 脚踝
 */
static const std::vector<std::pair<int, int>> COCO_POSE_SKELETON = {
    // 面部连接
    {0,1}, {0,2}, {1,3}, {2,4},
    // 头部到肩膀
    {3,5}, {4,6},
    // 手臂
    {5,7}, {7,9}, {6,8}, {8,10},
    // 躯干
    {5,6}, {5,11}, {6,12}, {11,12},
    // 腿部
    {11,13}, {13,15}, {12,14}, {14,16}
};

} // namespace yolos_edgeplatform

#endif // YOLOS_EDGEPLATFORM_COMMON_HPP
